<?php
/**
 * 基础的模型类
 * 
 * 派生时确定数据库的表名，以及相应的类名
 * 必须相同 ，比如 user 表对应于 user 类
 *
 * @author <judasnow@gmail.com>
 */
abstract class Base_model extends CI_Model{
	 private $_CI;
	 private $_table_name;
	 public function __construct( $table_name ){
		 $this->_CI =& get_instance();
	 	 $this->_table_name = $table_name;
	 }

	 private function get_result( $res ){
		 if( !empty( $res ) ){
			 return $res->result_array();
		 }else{
			 //@todo 此处应该使用一个 null 对象类
			 return '';
		 }
	 }

	 /**
	  * 计算该数据表中符合要求的记录的个数
	  *
	  * @param array $cond 需要符合的条件
	  * @return int 符合条件的记录的个数
	  */
	 public function count_all( $cond = array() ){
		 $this->db->where( $cond );
		 return $this->db->count_all_results( $this->_table_name );
	 }

	 /**
	  * 获得数据库中该表的满足条件的全部数据
	  *
	  * @todo 可能不需要这个函数
	  * @return array 
	  */
	  public function find_all( $cond = array() , $order_by = '' , $per_pager = '' , $offset = '' ){
		 if( !empty( $order_by ) ){
			 $this->db->order_by( $order_by['title'] , $order_by['order'] );
		 }
		 if( !empty( $cond ) ){
			 $this->db->where( $cond );		 
		 }
		 $res = $this->db->get( $this->_table_name , $per_pager , $offset );
		 return $this->get_result( $res );
	  } 

	 /**
	  * 根据提供的条件在数据库中
	  * 查询相应的记录信息，并生
	  * 成相应的记录的对象 
	  *
	  * @param array $cond 查找记录的条件
	  * 会直接应用于 sql 的 where 子句
	  * @param bool $creade_obj 为真才返回相应的对象
	  * 否则仅仅返回相应的查找结果信息数组
	  *
	  * @return mixed 查找用户的结果，如果结果唯一，则返回唯一的记录对象
	  * 否则返回全部对象的一个数组
	  */
	 public function find( $cond = array() , $creade_obj = FALSE ){
	 /*{{{*/
		 $this->db->where( $cond );
		 $res = $this->db->get( $this->_table_name );
		 $num_rows = $res->num_rows();
		 //判断返回的结果是一条还是多条
		 if( $num_rows == 1 ){
			 //唯一结果
			 //数据库中获取的信息
			 $row = $res->result_array();
			 if( $creade_obj ){
				 //如果需要生成对象
			 	 return $this->create_object( $row[0] );
			 }else{
				 return $row[0];
			 }
		 }elseif( $num_rows > 1 ){
			 //多于一个的结果
			 //默认返回数组
			 $row = $res->result_array();
			 if( $creade_obj ){
				 foreach( $row as $no=>$value ){
					$this->_CI->load->library( $this->_table_name , $value );
					$object_array[$no] = $this->_CI->{$this->_table_name};
				 }
				 return $object_array;
			 }else{
				 return $row;
			 }
		 }
		 //@todo 没有响应的记录存在 返回一个 null 对象
		 return '';

	 }/*}}}*/

	 /**
	  * 根据数据库中提供的信息创建相应的对象
	  *
	  * @param $value 该对象的属性 
	  */
	 public function create_object( $value ){
	 /*{{{*/
		 //@todo 不知道 CI 的对象机制是怎样的 
		 //生成多个同名对象的时候会不会重复 
		 //如果已经存在相应的对象 
		 //则销毁之 unset()
		 /*if( isset( $this->_CI->{$this->_table_name} ) ){
		 
			 unset( $this->_CI->{$this->_table_name} );
		 }*/

		 $this->_CI->load->library( $this->_table_name , $value );
		 return $this->_CI->{$this->_table_name};
	 }/*}}}*/

	 /**
	  * 在用户更新对象的相关信息后（数据库中），
	  * 更新该对象的信息为最新的版本，使内存中的信息同数据库中
	  * 的保持同步
	  * 
	  * @param array $cond 在数据库中当前对象的唯一标志
	  * @return array $info 
	  */
	 private function reload( $cond ){
	 /*{{{*/
		 $this->db->where( $cond );
		 $res = $this->db->get( $this->_table_name );
		 $num_rows = $res->num_rows();

		 if( $num_rows == 1 ){
			 $row = $res->result_array();		 
		 	 return $row[0];
		 }else{
			 //数据库中没有相应的记录，出现异常，记录日志
			 log_message( 'error' , 'reload 对象信息时出错.' );
			 return FALSE;
		 }
	 }/*}}}*/

	 /**
	  * 测试系统中满足某一条件的记录是否
	  * 已经存在
	  *
	  * @param array $cond 需要满足的条件
	  * @return bool 不存在返回FALSE，否则返回TRUE ( 如果存在 id 属性则返回 id )
	  */
	 public function is_exists( $cond ){
	 /*{{{*/
		 $this->db->where( $cond );
		 $res = $this->db->get( $this->_table_name );
		 if( $res->num_rows() == 0 ){
			 //结果数为 0 证明该记录在系统中不存在
			 return FALSE;
		 }else{
			 //查询返回的结果数不为 0
			 //证明满足条件的记录已经存在于系统之中
		 	 return isset( $row['id'] ) ? $row['id'] : TRUE;
		 }
	 }/*}}}*/

	 /**
	  * 添加一条信息到数据库中
	  *
	  * @param array $info 需要写入的记录
	  * @return bool 写入成功则返回 TRUE，否则返回 FALSE ( 判断的标准为 查看影响的行数 是否为 1 ) 
	  */
	 public function add_new( $info ){
	 /*{{{*/
		 $this->db->insert( $this->_table_name , $info );
		 $affected_rows = $this->db->affected_rows();
		 if( $affected_rows != 1 ){
			 $last_query = $this->db->last_query();
			 throw new Exception( "添加新的数据库记录时出错 SQL=[$last_query]"  );	
		 }
	 }/*}}}*/

	 public function del( $cond ){
	 /*{{{*/
		 if( !$this->db->delete( $this->_table_name , $cond ) ){
			 log_message( 'error' , '删除记录时失败 SQL=[' .  $this->db->last_query() . ']' );
			 throw new RuntimeException( '删除记录时异常 SQL=[' . $this->db->last_query() . ']' );
		 }
	 }/*}}}*/

	 /**
	  * 更新数据库中指定的信息
	  *
	  * @param array $infos 需要更新的信息本身
	  * @param array $where 定位需更新的记录信息 
	  */
	 public function update( $infos , $where ){
	 /*{{{*/
		 $this->db->where( $where );
		 if( !$this->db->update( $this->_table_name , $infos ) ){
			 //如果数据库操作失败，记录到日志文件中去
			 log_message( 'error' , '数据库更新失败 SQL=[' .  $this->db->last_query() . ']' );
			 throw new RuntimeException( '数据库更新失败 SQL=[' .  $this->db->last_query() . ']' );
		 }
	 }/*}}}*/
}

